package com.gzx.plugin.data.wckj.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.gzx.plugin.data.core.consts.CompanyConstants;
import com.gzx.plugin.data.core.utils.BatchNumberUtils;
import com.gzx.plugin.data.wckj.api.ApiResponse;
import com.gzx.plugin.data.wckj.api.CaseInfo;
import com.gzx.plugin.data.wckj.api.CaseResult;
import com.gzx.plugin.data.wckj.api.DebtorInfo;
import com.gzx.plugin.data.wckj.entity.DataWckjYwyhid;
import com.gzx.plugin.data.wckj.entity.JudgeLoanInfo;
import com.gzx.plugin.data.wckj.entity.JudgeUserInfo;
import com.gzx.plugin.data.wckj.mapper.DataWckjYwyhidMapper;
import com.gzx.plugin.data.wckj.mapper.WckjJudgeLoanInfoDao;
import com.gzx.plugin.data.wckj.mapper.WckjJudgeUserInfoDao;
import com.gzx.plugin.data.wckj.service.TjzyWckjService;
import com.gzx.tjzy.feign.GzxCaseFeign;
import com.gzx.tjzy.feign.GzxDebtorInfoFeign;
import com.gzx.tjzy.feign.GzxDebtorLiaisonFeign;
import com.gzx.tjzy.feign.req.debtor.GzxDebtorInfoReqDto;
import com.gzx.tjzy.feign.req.gzxcase.GzxCaseDetailReqDto;
import com.gzx.tjzy.feign.req.gzxcase.GzxCaseReqDto;
import com.gzx.tjzy.feign.req.liaison.GzxDebtorLiaisonReqDto;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import vip.xiaonuo.common.util.CommonCardIDUtil;
import vip.xiaonuo.common.util.CommonCryptogramUtil;
import vip.xiaonuo.common.util.CommonDateUtil;
import vip.xiaonuo.common.util.CommonSleepUtil;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author zjt
 * @description
 * @date 2025/2/14 09:13
 */
@Slf4j
@Service
@DS("data")
@RequiredArgsConstructor
public class TjzyWckjServiceImpl implements TjzyWckjService {

    private final DataWckjYwyhidMapper ywyhidMapper;

    private final WckjJudgeLoanInfoDao loanInfoDao;

    private final WckjJudgeUserInfoDao userInfoDao;

    private final GzxCaseFeign caseFeign;

    private final GzxDebtorInfoFeign debtorInfoFeign;

    private final GzxDebtorLiaisonFeign debtorLiaisonFeign;

    /**
     * 微财科技案件开始同步
     */
    @Override
    public void startSynchronization(String projectCode) {
        List<ApiResponse> apiResponseList = CaseResult.map.get(projectCode);
        if (CollectionUtil.isNotEmpty(apiResponseList)) {
            String batchNumber = BatchNumberUtils.getBatchNumber(CompanyConstants.WCKJ_COMPANY_CODE);
            for (Map.Entry<String, List<ApiResponse>> entry : CaseResult.map.entrySet()) {
                List<JudgeLoanInfo> loanInfoList = new ArrayList<>();
                List<JudgeUserInfo> userInfoList = new ArrayList<>();
                for (ApiResponse apiResponse : entry.getValue()) {
                    loanInfoList.addAll(apiResponse.getLoan());
                    userInfoList.addAll(apiResponse.getUserInfo());
                }
                start(batchNumber, entry.getKey(), loanInfoList, userInfoList);
            }
        }
    }

    /**
     * 手动同步数据
     */
    @Override
    public void manualStartSynchronization(String projectCode) {
        String batchNumber = BatchNumberUtils.getBatchNumber(CompanyConstants.WCKJ_COMPANY_CODE);
        String pp = null;
        if (projectCode.equals(CompanyConstants.WCKJ_PROJECT_CODE_M4)) {
            pp = "M4+";
        } else if (projectCode.equals(CompanyConstants.WCKJ_PROJECT_CODE_M7)) {
            pp = "M7+";
        } else {
            pp = "M12+";
        }
        List<String> ywyhidList = ywyhidMapper.selectList(Wrappers.<DataWckjYwyhid>lambdaQuery()
                .select(DataWckjYwyhid::getYwyhId)
                .eq(DataWckjYwyhid::getCaseBatch, pp)
                .ge(DataWckjYwyhid::getCreateTime, CommonDateUtil.getCurrentMonthFirstDay())).stream().map(DataWckjYwyhid::getYwyhId).toList();
        List<JudgeLoanInfo> loanInfoList = new ArrayList<>();
        List<JudgeUserInfo> userInfoList = new ArrayList<>();
        List<List<String>> ywyhidBatchList = Lists.partition(ywyhidList, 500);
        for (List<String> ywyhidBatch : ywyhidBatchList) {
            loanInfoList.addAll(loanInfoDao.selectList(Wrappers.<JudgeLoanInfo>lambdaQuery()
                    .in(JudgeLoanInfo::getYwyhId, ywyhidBatch)
                    .gt(JudgeLoanInfo::getCreateTime, CommonDateUtil.getCurrentMonthFirstDay())));
            userInfoList.addAll(userInfoDao.selectList(Wrappers.<JudgeUserInfo>lambdaQuery()
                    .in(JudgeUserInfo::getYwyhId, ywyhidBatch)
                    .gt(JudgeUserInfo::getCreateTime, CommonDateUtil.getCurrentMonthFirstDay())));
            CommonSleepUtil.sleep100();
        }
        start(batchNumber, projectCode, loanInfoList, userInfoList);
    }

    private void start(String batchNumber, String projectCode, List<JudgeLoanInfo> loanInfoList, List<JudgeUserInfo> userInfoList) {
        Map<String, List<JudgeLoanInfo>> loanInfoMap = loanInfoList.stream().collect(Collectors.groupingBy(JudgeLoanInfo::getYwyhId));
        Map<String, JudgeUserInfo> userInfoMap = userInfoList.stream()
                .collect(Collectors.toMap(
                        JudgeUserInfo::getYwyhId,
                        Function.identity(),
                        (existing, replacement) -> replacement));
        CaseInfo caseInfo = buildCaseInfo(batchNumber, projectCode, loanInfoMap, userInfoMap);
        DebtorInfo debtorInfo = buildDebtorInfo(projectCode, userInfoList);
        tjzyWckjCaseProcess(caseInfo, debtorInfo);
    }

    /**
     * 构建案件主表和明细
     *
     * @param batchNumber
     * @param projectCode
     * @param loanInfoMap
     * @param userInfoMap
     * @return
     */
    private CaseInfo buildCaseInfo(String batchNumber, String projectCode, Map<String, List<JudgeLoanInfo>> loanInfoMap, Map<String, JudgeUserInfo> userInfoMap) {
        List<GzxCaseReqDto> caseReqDtoList = new ArrayList<>();
        List<GzxCaseDetailReqDto> caseDetailReqDtoList = new ArrayList<>();
        for (Map.Entry<String, List<JudgeLoanInfo>> entry : loanInfoMap.entrySet()) {
            List<JudgeLoanInfo> loanInfoList = entry.getValue();
            //组织案件主表数据
            BigDecimal sumLoanAmount = loanInfoList.stream()
                    .map(item -> Optional.ofNullable(item.getLoanAmount()).orElse(BigDecimal.ZERO))
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            GzxCaseReqDto caseReqDto = new GzxCaseReqDto();
            caseReqDto.setCompanyCode(CompanyConstants.WCKJ_COMPANY_CODE);
            caseReqDto.setProductCode(CompanyConstants.WCKJ_PRODUCT_CODE);
            caseReqDto.setProjectCode(projectCode);
            caseReqDto.setBatchNumber(batchNumber);
            if (userInfoMap.containsKey(entry.getKey())) {
                JudgeUserInfo userInfo = userInfoMap.get(entry.getKey());
                caseReqDto.setDebtorName(userInfo.getName());
                caseReqDto.setDebtorCardId(CommonCryptogramUtil.doSm1AesEncrypt(userInfo.getIdNo()));
                caseReqDto.setPartnerBusinessId(userInfo.getYwyhId());
                caseReqDto.setDebtorPhone(CommonCryptogramUtil.doSm1AesEncrypt(userInfo.getMobileList().contains(",") ? userInfo.getMobileList().split(",")[0] : userInfo.getMobileList()));
                caseReqDto.setDebtorSex("M".equals(userInfo.getGender()) ? 1 : 2);
            }
            caseReqDto.setCaseStatus(1); //待分配
            caseReqDto.setOverdueStatus(1);
            caseReqDto.setOverdueAmount(BigDecimal.ZERO);
            caseReqDto.setLoanAmount(sumLoanAmount);
            caseReqDtoList.add(caseReqDto);
            //组织案件明细表
            for (JudgeLoanInfo loanInfo : loanInfoList) {
                GzxCaseDetailReqDto caseDetailReqDto = new GzxCaseDetailReqDto();
                BeanUtils.copyProperties(loanInfo, caseDetailReqDto);
                caseDetailReqDto.setBatchNumber(batchNumber);
                caseDetailReqDto.setDebtorCardId(caseReqDto.getDebtorCardId());
                caseDetailReqDto.setBankAccount(CommonCryptogramUtil.doSm1AesEncrypt(loanInfo.getBankAccount()));
                caseDetailReqDto.setPartnerBusinessId(loanInfo.getYwyhId());
                caseDetailReqDto.setAllDetail(JSON.toJSONString(loanInfo));
                caseDetailReqDtoList.add(caseDetailReqDto);
            }
        }
        return new CaseInfo(caseReqDtoList, caseDetailReqDtoList);
    }

    /**
     * 构建欠款人和三方联系人信息
     *
     * @param projectCode
     * @param userInfoList
     * @return
     */
    private DebtorInfo buildDebtorInfo(String projectCode, List<JudgeUserInfo> userInfoList) {
        List<GzxDebtorInfoReqDto> debtorInfoReqDtoList = new ArrayList<>();
        List<GzxDebtorLiaisonReqDto> liaisonInfoList = new ArrayList<>();
        for (JudgeUserInfo userInfo : userInfoList) {
            //构建欠款人信息
            GzxDebtorInfoReqDto debtorInfoReqDto = setDebtorInfo(projectCode, userInfo);
            debtorInfoReqDtoList.add(debtorInfoReqDto);
            //构建三方联系人信息
            List<GzxDebtorLiaisonReqDto> detailInfoReqDto = setDebtorLiaisonInfo(projectCode, userInfo);
            liaisonInfoList.addAll(detailInfoReqDto);
        }
        return new DebtorInfo(debtorInfoReqDtoList, liaisonInfoList);
    }

    private GzxDebtorInfoReqDto setDebtorInfo(String projectCode, JudgeUserInfo userInfo) {
        GzxDebtorInfoReqDto debtorInfoReqDto = new GzxDebtorInfoReqDto();
        debtorInfoReqDto.setDebtorName(userInfo.getName());
        debtorInfoReqDto.setDebtorBirth(userInfo.getBirth());
        debtorInfoReqDto.setProjectCode(projectCode);
        //获取年龄
        debtorInfoReqDto.setDebtorAge(CommonCardIDUtil.getAgeByBirth(userInfo.getBirth()));
        debtorInfoReqDto.setDebtorProvince(userInfo.getIdNoArea());
        debtorInfoReqDto.setDebtorCity(userInfo.getIdNoArea());
        debtorInfoReqDto.setDebtorAddress(userInfo.getAddress());
        debtorInfoReqDto.setDebtorNowAddress(userInfo.getNowAddress());
        debtorInfoReqDto.setDebtorAccountBalance(userInfo.getAccountBalance());
        debtorInfoReqDto.setDebtorCardId(CommonCryptogramUtil.doSm1AesEncrypt(userInfo.getIdNo()));
        debtorInfoReqDto.setDebtorPhone(userInfo.getMobileList().contains(",") ? CommonCryptogramUtil.doSm1AesEncrypt(userInfo.getMobileList().split(",")[0]) : CommonCryptogramUtil.doSm1AesEncrypt(userInfo.getMobileList()));
        debtorInfoReqDto.setDebtorSex("M".equals(userInfo.getGender()) ? 1 : 2);
        return debtorInfoReqDto;
    }

    private List<GzxDebtorLiaisonReqDto> setDebtorLiaisonInfo(String projectCode, JudgeUserInfo userInfo) {
        List<GzxDebtorLiaisonReqDto> liaisonInfoList = new ArrayList<>();
        String[] mobileList = userInfo.getMobileList().split(",");
        for (int i = 0; i < mobileList.length; i++) {
            liaisonInfoList.add(new GzxDebtorLiaisonReqDto(projectCode, CommonCryptogramUtil.doSm1AesEncrypt(userInfo.getIdNo()), "本人", userInfo.getName(), CommonCryptogramUtil.doSm1AesEncrypt(mobileList[i]), 5, 1));
        }
        //联系人A
        liaisonInfoList.add(new GzxDebtorLiaisonReqDto(projectCode, CommonCryptogramUtil.doSm1AesEncrypt(userInfo.getIdNo()), userInfo.getSpecialRelation(), userInfo.getSpecialName(), CommonCryptogramUtil.doSm1AesEncrypt(userInfo.getSpecialMobileNo()), 5, 1));
        //联系人B
        liaisonInfoList.add(new GzxDebtorLiaisonReqDto(projectCode, CommonCryptogramUtil.doSm1AesEncrypt(userInfo.getIdNo()), userInfo.getSpecialRelation2(), userInfo.getSpecialName2(), CommonCryptogramUtil.doSm1AesEncrypt(userInfo.getSpecialMobileNo2()), 5, 1));
        return liaisonInfoList;
    }

    private void tjzyWckjCaseProcess(CaseInfo caseInfo, DebtorInfo debtorInfo) {
        Thread.startVirtualThread(() -> {
            //发送案件主表数据
            long caseStartTime = System.currentTimeMillis();
            List<List<GzxCaseReqDto>> batchCaseList = Lists.partition(caseInfo.getCaseList(), 2000);
            for (List<GzxCaseReqDto> batchCase : batchCaseList) {
                caseFeign.caseSync(batchCase);
                CommonSleepUtil.sleep100();
            }
            log.info("案件主表数据同步完成，共计：{}条，耗时:{}", caseInfo.getCaseList().size(), System.currentTimeMillis() - caseStartTime);
            //发送案件明细数据
            long caseDetailStartTime = System.currentTimeMillis();
            List<List<GzxCaseDetailReqDto>> caseDetailList = Lists.partition(caseInfo.getCaseDetailList(), 2000);
            for (List<GzxCaseDetailReqDto> batchCaseDetail : caseDetailList) {
                caseFeign.caseDetailSync(batchCaseDetail);
                CommonSleepUtil.sleep100();
            }
            log.info("案件明细数据同步完成，共计：{}条，耗时:{}", caseInfo.getCaseDetailList().size(), System.currentTimeMillis() - caseDetailStartTime);
            //发送欠款人数据
            long debtorStartTime = System.currentTimeMillis();
            List<List<GzxDebtorInfoReqDto>> batchDebtorList = Lists.partition(debtorInfo.getDebtorInfoReqDtoList(), 2000);
            for (List<GzxDebtorInfoReqDto> batchDebtor : batchDebtorList) {
                debtorInfoFeign.sync(batchDebtor);
                CommonSleepUtil.sleep100();
            }
            log.info("欠款人数据同步完成，共计：{}条，耗时:{}", debtorInfo.getDebtorInfoReqDtoList().size(), System.currentTimeMillis() - debtorStartTime);
            //发送三方联系人数据
            long liaisonStartTime = System.currentTimeMillis();
            List<List<GzxDebtorLiaisonReqDto>> batchLiaisonList = Lists.partition(debtorInfo.getDebtorLiaisonReqDtoList(), 2000);
            for (List<GzxDebtorLiaisonReqDto> batchLiaison : batchLiaisonList) {
                debtorLiaisonFeign.sync(batchLiaison);
                CommonSleepUtil.sleep100();
            }
            log.info("三方联系人数据同步完成，共计：{}条，耗时:{}", debtorInfo.getDebtorLiaisonReqDtoList().size(), System.currentTimeMillis() - liaisonStartTime);
        });
    }
}
